import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { Role } from './role.entity';
import { Permission } from '../permissions/permission.entity';

/**
 * 角色服务
 * 处理角色相关的业务逻辑
 */
@Injectable()
export class RolesService {
  constructor(
    @InjectRepository(Role)
    private roleRepository: Repository<Role>,
    @InjectRepository(Permission)
    private permissionRepository: Repository<Permission>,
  ) {}

  /**
   * 创建角色
   * @param createRoleDto 创建角色数据
   * @returns 创建的角色信息
   */
  async create(createRoleDto: CreateRoleDto): Promise<Role> {
    const { name, description, permissionIds } = createRoleDto;

    // 检查角色名是否已存在
    const existingRole = await this.roleRepository.findOne({
      where: { name },
    });
    if (existingRole) {
      throw new ConflictException('角色名已存在');
    }

    // 创建角色
    const role = this.roleRepository.create({
      name,
      description,
    });

    // 如果提供了权限ID，关联权限
    if (permissionIds && permissionIds.length > 0) {
      const permissions =
        await this.permissionRepository.findByIds(permissionIds);
      role.permissions = permissions;
    }

    return this.roleRepository.save(role);
  }

  /**
   * 获取角色列表
   * @param page 页码
   * @param limit 每页数量
   * @returns 角色列表和总数
   */
  async findAll(page: number = 1, limit: number = 10) {
    const [roles, total] = await this.roleRepository.findAndCount({
      relations: ['permissions'],
      skip: (page - 1) * limit,
      take: limit,
      order: { createdAt: 'DESC' },
    });

    return {
      data: roles,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  /**
   * 获取角色详情
   * @param id 角色ID
   * @returns 角色详情
   */
  async findOne(id: number): Promise<Role> {
    const role = await this.roleRepository.findOne({
      where: { id },
      relations: ['permissions', 'users'],
    });

    if (!role) {
      throw new NotFoundException('角色不存在');
    }

    return role;
  }

  /**
   * 更新角色信息
   * @param id 角色ID
   * @param updateRoleDto 更新数据
   * @returns 更新后的角色信息
   */
  async update(id: number, updateRoleDto: UpdateRoleDto): Promise<Role> {
    const role = await this.findOne(id);
    const { name, description, permissionIds } = updateRoleDto;

    // 如果更新角色名，检查是否已存在
    if (name && name !== role.name) {
      const existingRole = await this.roleRepository.findOne({
        where: { name },
      });
      if (existingRole) {
        throw new ConflictException('角色名已存在');
      }
    }

    // 更新基本信息
    if (name) role.name = name;
    if (description !== undefined) role.description = description;

    // 更新权限关联
    if (permissionIds !== undefined) {
      if (permissionIds.length > 0) {
        const permissions =
          await this.permissionRepository.findByIds(permissionIds);
        role.permissions = permissions;
      } else {
        role.permissions = [];
      }
    }

    return this.roleRepository.save(role);
  }

  /**
   * 删除角色
   * @param id 角色ID
   */
  async remove(id: number): Promise<void> {
    const role = await this.findOne(id);

    // 检查是否有用户关联此角色
    if (role.users && role.users.length > 0) {
      throw new ConflictException('该角色下还有用户，无法删除');
    }

    await this.roleRepository.remove(role);
  }

  /**
   * 切换角色状态
   * @param id 角色ID
   * @returns 更新后的角色信息
   */
  async toggleStatus(id: number): Promise<Role> {
    const role = await this.findOne(id);
    role.isActive = !role.isActive;
    return this.roleRepository.save(role);
  }

  /**
   * 根据名称查找角色
   * @param names 角色名称数组
   * @returns 角色列表
   */
  async findByNames(names: string[]): Promise<Role[]> {
    return this.roleRepository
      .createQueryBuilder('role')
      .where('role.name IN (:...names)', { names })
      .getMany();
  }
}